﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sworm
{
    struct ColumnMappedAccessor
    {
        public readonly DbAccessor accessor;
        public readonly ColumnData column;

        public ColumnMappedAccessor(DbAccessor accessor, ColumnData column)
        {
            this.accessor = accessor;
            this.column = column;
        }
    }

    // Given property Prop, we can easily construct a compiled lambda expression in the form:
    //
    //    (object instance, DbAccessor accessor) => instance.Prop = accessor.GetSingle()
    //
    // This is because there should be at most 1 declared method whose return type
    // matches P.PropertyType - for example, GetSingle() is the only method returning
    // a Single. If there is no matching declared method, we can assume it's not mappable
    // or we can try to do a smarter conversion.
    //
    // We can also have user-defined converions depend on this, which could potentially
    // avoid unecessary boxing.
    public struct DbAccessor
    {
        private readonly System.Data.IDataReader reader;
        private readonly int index;

        public DbAccessor(System.Data.IDataReader reader, int columnIndex)
        {
            this.reader = reader;
            this.index = columnIndex;
        }

        public object GetObject()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetValue(index);
        }

        public byte[] GetByteArray()
        {
            if (reader.IsDBNull(index)) return null;
            return (byte[])reader.GetValue(index);
        }

        public Single GetSingle()
        {
            return (Single)reader.GetDouble(index);
        }

        public Single? GetSingleNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return (Single)reader.GetDouble(index);
        }

        public Boolean GetBoolean()
        {
            return reader.GetBoolean(index);
        }

        public Boolean? GetBooleanNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetBoolean(index);
        }

        public Byte GetByte()
        {
            return reader.GetByte(index);
        }

        public Byte? GetByteNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetByte(index);
        }

        public Char GetChar()
        {
            return reader.GetChar(index);
        }

        public Char? GetCharNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetChar(index);
        }

        public Guid GetGuid()
        {
            return reader.GetGuid(index);
        }

        public Guid? GetGuidNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetGuid(index);
        }

        public Int16 GetInt16()
        {
            return reader.GetInt16(index);
        }

        public Int16? GetInt16Nullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetInt16(index);
        }

        public Int32 GetInt32()
        {
            return reader.GetInt32(index);
        }

        public Int32? GetInt32Nullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetInt32(index);
        }

        public Int64 GetInt64()
        {
            return reader.GetInt64(index);
        }

        public Int64? GetInt64Nullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetInt64(index);
        }

        public Double GetDouble()
        {
            return reader.GetDouble(index);
        }

        public Double? GetDoubleNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetDouble(index);
        }

        public String GetString()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetString(index);
        }

        public Decimal GetDecimal()
        {
            return reader.GetDecimal(index);
        }

        public Decimal? GetDecimalNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetDecimal(index);
        }

        public DateTime GetDateTime()
        {
            return reader.GetDateTime(index);
        }

        public DateTime? GetDateTimeNullable()
        {
            if (reader.IsDBNull(index)) return null;
            return reader.GetDateTime(index);
        }
    }
}